// Copyright (c) 2023 刻BITTER
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.


#pragma once

#include <type_traits>

#include "data_basic.hpp"
#include "scheduler_tick.hpp"


namespace scheduler_basic {

    /**
     * @brief 用来方便实现简单的轮询延时操作
     *
     * @tparam TimeSource
     */
    template <typename TimeSource>
    class TimeCycle {
       public:
        using TimeType = typename TimeSource::TimeType;

       private:
        TimeSource _time;

       public:
        TimeCycle() {
            reset();
        }


        void reset() {
            _time.reset();
        }


        /**
         * @brief 周期性延时指定的时间
         *
         * 每次延时结束时返回true，同时自动更新参考时间，从而开启下一个延时周期。
         *
         * @param duration 时间
         * @return true    一个延时周期结束
         * @return false   当前延时周期未结束
         */
        bool cycle(TimeType duration) {
            if (this->expired(duration)) {
                reset();
                return true;
            }
            return false;
        }


        /**
         * @brief 非阻塞延时指定的时间
         *
         * 延时结束不自动更新参考时间，一次延时结束后，返回值保持为true。
         *
         * @param duration 时间
         * @return true    已经过了指定的时间
         * @return false   延时尚未结束
         */
        bool expired(TimeType duration) {
            return _time.diff() > duration;
        }


        /**
         * @brief 非阻塞延时指定的时间
         * 
         * 与expired 相同，只是返回值逻辑相反，一次延时结束后，返回值保持为false
         * 
         * @param duration 
         * @return true 
         * @return false 
         */
        bool wait(TimeType duration) {
            return !expired(duration);
        }
    };
}  // namespace scheduler_basic